package cc.shacocloud.mirage.kotlin.restful

import cc.shacocloud.mirage.kotlin.isSuspendingFunction
import cc.shacocloud.mirage.restful.*
import cc.shacocloud.mirage.restful.bind.converter.json.Jackson2ObjectMapperBuilder
import cc.shacocloud.mirage.utils.reflection.ParameterNameDiscoverer
import com.fasterxml.jackson.databind.ObjectMapper
import io.vertx.core.Vertx

/**
 * 基于 kotlin 实现的请求映射处理器
 * @author 思追(shaco)
 *
 */
class KotlinRequestMappingHandler(
    vertx: Vertx,
    parameterNameDiscoverer: ParameterNameDiscoverer,
    objectMapper: ObjectMapper
) :
    MirageRequestMappingHandler(vertx, parameterNameDiscoverer, objectMapper) {

    constructor(vertx: Vertx, parameterNameDiscoverer: ParameterNameDiscoverer) :
            this(vertx, parameterNameDiscoverer, Jackson2ObjectMapperBuilder.json().build<ObjectMapper>())

    /**
     * 校验方法映射处理器
     */
    override fun validateMethodMapping(handlerMethod: HandlerMethod, mapping: RequestMappingInfo) {
        // 如果是 kotlin  协程方法则不验证
        if (!isSuspendingFunction(handlerMethod)) {
            super.validateMethodMapping(handlerMethod, mapping)
        }

    }

    /**
     * 创建内部处理器方法
     */
    override fun createInvocableHandlerMethod(handlerMethod: HandlerMethod): VertxInvokeHandler {
        // 如果是kotlin的协程方法则使用 KotlinVertxInvocableHandlerMethod 封装的处理器方法
        if (isSuspendingFunction(handlerMethod)) {
            val invocableHandlerMethod = KotlinVertxInvocableHandlerMethod(handlerMethod)

            invocableHandlerMethod.setParameterNameDiscoverer(parameterNameDiscoverer)
            invocableHandlerMethod.setWebDataBinderFactory(createDataBinderFactory())

            returnValueHandlerComposite?.let { invocableHandlerMethod.setReturnValueHandlers(it) }

            // 拓展协程方法参数解析器
            val methodArgumentResolver = argumentResolverComposite ?: HandleMethodArgumentResolverComposite()
            invocableHandlerMethod.setHandlerMethodArgumentResolvers(methodArgumentResolver)

            return invocableHandlerMethod
        }

        return super.createInvocableHandlerMethod(handlerMethod)
    }


}